import * as config from 'config'
import * as request from 'supertest'
import {freeCoinByInviter, freeCoinBySharer, freeCoinBySharing, freeCoinDefault} from "../../api/utils";
import GM from "../../database/models/gm";
import {PlayerModel} from "../../database/models/player";
import app from '../../serverApp'
import createClient from "../../utils/redis";
import {expect, setupTestEnv, tearDownTestEnv, TestEnv} from "./helper";

describe('player api', () => {

  let redisClient = null
  let inviteCode = null
  let gm = null
  let env: TestEnv = null

  before(async () => {
    env = await setupTestEnv()
    redisClient = createClient()
  })

  after(async () => {
    await tearDownTestEnv()
  })

  beforeEach(async () => {
    inviteCode = Date.now().toString().slice(-6)
    gm = await GM.create({
      username: 't' + inviteCode,
      password: 't' + inviteCode,
      role: 'level2',
      spendGold: 0,
      inviteCode
    })
  })

  afterEach(async () => {
    await GM.deleteMany({})
  })

  /*
  it('[接口废弃]游客登录-信息获取-绑定GM ', async function () {

    let token = ''
    await request(app)
      .post('/player/login/tourist')
      .then(res => {
        // jwt token
        token = res.body.data.token
      })

    await request(app)
      .get('/player/info')
      .set({'x-jwt': token})
      .then(() => {
      })

    await request(app)
      .post('/player/bindGM')
      .set({'x-jwt': token})
      .send({inviteCode})
      .then(res => {
        expect(res.body).to.have.properties({ok: true})
      })
  })
  */

  context(`手机号`, async () => {
    const phoneNum = '13250839904'
    beforeEach(async () => {
      await PlayerModel.update({phone: phoneNum}, {$set: {phone: Math.random().toString(36)}})
      redisClient.lpush('smsCodes', [`123456`, `654321`], function () {
      })
    })

    it('html中获取验证码注册,下载app，app验证码登录', async function () {
      const shareEr = await PlayerModel.findById(env.player).lean()
      await request(app)
        .post('/player/getSMSCode')
        .send({phoneNum})
        .expect(200)
        .then(res => {
          expect(res.body).to.have.properties({
            ok: true
          })
        })

      const tempSmsCode = await redisClient.getAsync(phoneNum)
      await request(app)
        .post('/player/register/invite')
        .send({
          phoneNum,
          smsCode: tempSmsCode,
          inviteCode,
          shareCode: env.player.shortId,
          requestBy: 'html'
        })
        .then(res => {
          // jwt token
          expect(res.body).have.properties({ok: true})
        })

      const p = await PlayerModel.findOne({phone: phoneNum}).lean()
      expect(p.inviteBy._id.toString()).to.equal(gm.id)
      expect(p.shareBy._id.toString()).to.equal(env.player.id)
      expect(p.freeCoin).to.equal(freeCoinDefault + freeCoinByInviter + freeCoinBySharer)

      const se = await PlayerModel.findById(env.player).lean()
      expect(se.freeCoin).to.equal(shareEr.freeCoin + freeCoinBySharing)

      await request(app)
        .post('/player/getSMSCode')
        .send({phoneNum})
        .expect(200)
      const codeNew = await redisClient.getAsync(phoneNum)

      let token = null
      await request(app)
        .post('/player/smsLogin/login')
        .send({phoneNum, smsCode: codeNew})
        .expect(200)
        .then(res => {
          expect(res.body).have.properties({ok: true})
          token = res.body.data.token
        })

      await request(app)
        .get('/player/info')
        .set({'x-jwt': token})
        .then(res => {
          expect(res.body).have.properties({ok: true})
        })

      await request(app)
        .post('/player/getSMSCode')
        .send({phoneNum})
        .expect(200)
      const codeNew2 = await redisClient.getAsync(phoneNum)

      let token2 = null
      await request(app)
        .post('/player/smsLogin/login')
        .send({phoneNum, smsCode: codeNew2})
        .expect(200)
        .then(res => {
          expect(res.body).have.properties({ok: true})
          token2 = res.body.data.token
        })

      await request(app)
        .get('/player/info')
        .set({'x-jwt': token})
        .expect(302)
    });

    it('app中获取验证码绑定关系注册，注册用户可以直接验证码登录，旧的token失效', async function () {
      const shareEr = await PlayerModel.findById(env.player).lean()
      await request(app)
        .post('/player/getSMSCode')
        .send({phoneNum})
        .expect(200)
        .then(res => {
          expect(res.body).to.have.properties({
            ok: true
          })
        })
      let token = null
      const tempSmsCode = await redisClient.getAsync(phoneNum)
      await request(app)
        .post('/player/register/invite')
        .send({
          phoneNum,
          smsCode: tempSmsCode,
          inviteCode,
          shareCode: env.player.shortId,
          requestBy: 'app'
        })
        .then(res => {
          // jwt token
          expect(res.body).have.properties({ok: true})
          token = res.body.data.token
        })

      const p = await PlayerModel.findOne({phone: phoneNum}).lean()
      expect(p.inviteBy._id.toString()).to.equal(gm.id)
      expect(p.shareBy._id.toString()).to.equal(env.player.id)
      expect(p.freeCoin).to.equal(freeCoinDefault + freeCoinByInviter + freeCoinBySharer)

      const se = await PlayerModel.findById(env.player).lean()
      expect(se.freeCoin).to.equal(shareEr.freeCoin + freeCoinBySharing)

      await request(app)
        .get('/player/info')
        .set({'x-jwt': token})
        .then(res => {
          expect(res.body).have.properties({ok: true})
        })

      await request(app)
        .post('/player/getSMSCode')
        .send({phoneNum})
        .expect(200)
      const codeNew2 = await redisClient.getAsync(phoneNum)

      let token2 = null
      await request(app)
        .post('/player/smsLogin/login')
        .send({phoneNum, smsCode: codeNew2})
        .expect(200)
        .then(res => {
          expect(res.body).have.properties({ok: true})
          token2 = res.body.data.token
        })

      await request(app)
        .get('/player/info')
        .set({'x-jwt': token})
        .expect(302)
    })

    it('app中获取验证码裸注册,登录后绑定GM or Player', async function () {
      const shareEr = await PlayerModel.findById(env.player).lean()
      await request(app)
        .post('/player/getSMSCode')
        .send({phoneNum})
        .expect(200)
        .then(res => {
          expect(res.body).to.have.properties({
            ok: true
          })
        })
      let token = null
      const tempSmsCode = await redisClient.getAsync(phoneNum)
      await request(app)
        .post('/player/register/invite')
        .send({
          phoneNum,
          smsCode: tempSmsCode,
          inviteCode: '',
          // shareCode: env.player.shortId,
          requestBy: 'app'
        })
        .then(res => {
          // jwt token
          expect(res.body).have.properties({ok: true})
          token = res.body.data.token
        })

      await request(app)
        .get('/player/info')
        .set({'x-jwt': token})
        .then(res => {
          expect(res.body).have.properties({ok: true})
        })

      const fCoin = (await PlayerModel.findOne({phone: phoneNum}).lean()).freeCoin
      await request(app)
        .post('/player/bindGM')
        .set({'x-jwt': token})
        .send({inviteCode})
        .then(res => {
          expect(res.body).to.have.properties({ok: true})
        })
      expect((await PlayerModel.findOne({phone: phoneNum}).lean()).inviteBy._id.toString()).to.equal(gm.id)
      expect((await PlayerModel.findOne({phone: phoneNum}).lean()).freeCoin).to.equal(fCoin + freeCoinByInviter)
      await request(app)
        .post('/player/bindGM')
        .set({'x-jwt': token})
        .send({inviteCode})
        .then(res => {
          expect(res.body).to.have.properties({ok: false})
        })

      const fCoin2 = (await PlayerModel.findOne({phone: phoneNum}).lean()).freeCoin
      await request(app)
        .post('/player/bindPlayer')
        .set({'x-jwt': token})
        .send({shareCode: env.player.shortId})
        .then(res => {
          expect(res.body).to.have.properties({ok: true})
        })
      const se = await PlayerModel.findById(env.player).lean()
      expect(se.freeCoin).to.equal(shareEr.freeCoin + freeCoinBySharing)

      expect((await PlayerModel.findOne({phone: phoneNum}).lean()).shareBy._id.toString()).to.equal(env.player._id.toString())
      expect((await PlayerModel.findOne({phone: phoneNum}).lean()).freeCoin).to.equal(fCoin2 + freeCoinBySharer)

      await request(app)
        .post('/player/bindPlayer')
        .set({'x-jwt': token})
        .send({shareCode: env.player.shortId})
        .then(res => {
          expect(res.body).to.have.properties({ok: false})
        })
    })

    it('分享者实际邀请超过十人无法拿更多奖励', async function () {
      const shareEr = await PlayerModel.findByIdAndUpdate(env.player, {sharedCount: 10}, {new: true}).lean()
      await request(app)
        .post('/player/getSMSCode')
        .send({phoneNum})
        .expect(200)
        .then(res => {
          expect(res.body).to.have.properties({
            ok: true
          })
        })
      let token = null
      const tempSmsCode = await redisClient.getAsync(phoneNum)
      await request(app)
        .post('/player/register/invite')
        .send({
          phoneNum,
          smsCode: tempSmsCode,
          inviteCode,
          shareCode: env.player.shortId,
          requestBy: 'app'
        })
        .then(res => {
          // jwt token
          expect(res.body).have.properties({ok: true})
          token = res.body.data.token
        })

      const p = await PlayerModel.findOne({phone: phoneNum}).lean()
      expect(p.inviteBy._id.toString()).to.equal(gm.id)
      expect(p.shareBy._id.toString()).to.equal(env.player.id)

      const se = await PlayerModel.findById(env.player).lean()
      expect(se.freeCoin).to.equal(shareEr.freeCoin)
    });

    it('修改个人信息', async function () {
      const info = {
        name: '6262哲楠',
        sex: 1
      }

      await request(app)
        .post('/player/changeInfo')
        .set({'x-jwt': env.jwt})
        .send({...info})
        .expect(200)
        .then(res => {
          expect(res.body).to.have.properties({
            ok: true
          })
        })

      const player = await PlayerModel.findById(env.player)
      expect(player.name).to.equal(info.name)
      expect(player.sex).to.equal(info.sex)
    })

  })
})
